Previous slide Next slide Toggle fullscreen Open presenter view
Программирование сетевых приложений
Средства языка для организации работы в сети
Программирование сетевых приложений
Содержание лекции
Распределенная обработка данных
Основы работы в сети
Клиент-серверная архитектура
Proxy-сервера
Internet-адресация
Сетевые классы и интерфейсы
Обзор сокетов
TCP/IP клиенты и серверы
Дейтаграммы (UDP)
Использование URL
Практические примеры на Qt
Средства языка для организации работы в сети
Программирование сетевых приложений
Распределенная обработка данных
Понятие распределенной системы
Совокупность независимых компьютеров, представляемых пользователю как единая система
Компоненты взаимодействуют через сеть
Общие характеристики:
Масштабируемость
Отказоустойчивость
Прозрачность доступа
Конкурентный доступ к ресурсам
Средства языка для организации работы в сети
Программирование сетевых приложений
Модели сетевой архитектуры
Модель OSI vs TCP/IP
(Подробное описание моделей OSI и TCP/IP рассмотрено в лекции 2. Ниже — краткая справка.)
OSI
TCP/IP
Протоколы
Роль в программировании
7. Прикладной
Прикладной
HTTP, FTP, DNS, SMTP
Основной уровень для разработчика
6. Представления
SSL/TLS, JPEG, JSON
Кодирование/шифрование данных
5. Сеансовый
NetBIOS, RPC
Управление сессиями
4. Транспортный
Транспортный
TCP, UDP
Сокеты, QTcpSocket, QUdpSocket
3. Сетевой
Интернет
IP, ICMP, ARP
Маршрутизация, адресация
2. Канальный
Сетевой доступа
Ethernet, Wi-Fi
Драйверы, NIC
1. Физический
Электрические сигналы
Кабели, оптоволокно
Для программиста сетевых приложений ключевые уровни: Транспортный (TCP/UDP сокеты) и Прикладной (HTTP, RPC).
Средства языка для организации работы в сети
Программирование сетевых приложений
Принципы маршрутизации и коммутации
Маршрутизация (Routing) на 3 уровне
Определение оптимального пути для пакетов
Использование таблиц маршрутизации
Протоколы динамической маршрутизации (OSPF, BGP)
Логическая адресация (IP-адреса)
Средства языка для организации работы в сети
Программирование сетевых приложений
Коммутация (Switching) на 2 уровне
Передача кадров между сегментами сети
Использование MAC-адресов
Создание таблиц коммутации
Виртуальные LAN (VLAN)
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы коммутации:
Канальная коммутация - установление выделенного канала
Пакетная коммутация - передача независимых пакетов
Сообщечная коммутация - передача цельных сообщений
Средства языка для организации работы в сети
Программирование сетевых приложений
Качество обслуживания (QoS - Quality of Service)
Параметры QoS:
Пропускная способность (Bandwidth) - максимальная скорость передачи
Задержка (Latency) - время передачи данных
Джиттер (Jitter) - изменение задержки
Потери пакетов (Packet Loss) - процент потерянных пакетов
Средства языка для организации работы в сети
Программирование сетевых приложений
Механизмы QoS:
Приоритизация трафика (Traffic Prioritization)
Контроль полосы пропускания (Bandwidth Management)
Управление очередями (Queue Management)
Формирование трафика (Traffic Shaping)
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы сетевых устройств по уровням OSI
Устройство
Уровни OSI
Функции
Концентратор (Hub)
1 (Физический)
Повторение сигналов
Мост (Bridge)
2 (Канальный)
Соединение сетевых сегментов
Коммутатор (Switch)
2 (Канальный)
Коммутация кадров по MAC-адресам
Маршрутизатор (Router)
3 (Сетевой)
Маршрутизация пакетов по IP-адресам
Шлюз (Gateway)
4-7 (Транспортный и выше)
Протокольная трансляция
Межсетевой экран (Firewall)
3-4 (Сетевой и транспортный)
Фильтрация трафика
Брандмауэр приложений
7 (Прикладной)
Фильтрация на уровне приложений
Средства языка для организации работы в сети
Программирование сетевых приложений
Клиент-серверная архитектура
Основные принципы
Клиент-серверная архитектура - это модель организации сетевого взаимодействия, при которой одна сторона (клиент) инициирует запрос, а другая сторона (сервер) обрабатывает этот запрос и возвращает ответ.
Роли участников:
Клиент - инициатор запроса, потребитель услуг
Сервер - исполнитель запроса, поставщик услуг
Точка взаимодействия - сокет (socket), через который происходит обмен данными
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы клиент-серверных архитектур
1. Двухуровневая архитектура (2-tier)
Клиент ←→ Сервер базы данных
Клиент содержит бизнес-логику и пользовательский интерфейс
Сервер управляет данными
Примеры: традиционные настольные приложения
Средства языка для организации работы в сети
Программирование сетевых приложений
2. Трехуровневая архитектура (3-tier)
Клиент ←→ Сервер приложений ←→ Сервер базы данных
Клиент - только пользовательский интерфейс
Сервер приложений - бизнес-логика
Сервер базы данных - хранение данных
Преимущества: лучшая масштабируемость и безопасность
Средства языка для организации работы в сети
Программирование сетевых приложений
3. Многоуровневая архитектура (n-tier)
Клиент ←→ Веб-сервер ←→ Сервер приложений ←→ Сервер базы данных
Дополнительные уровни для балансировки нагрузки, кэширования и т.д.
Современные веб-приложения и микросервисы
Средства языка для организации работы в сети
Программирование сетевых приложений
Принципы работы клиент-серверного взаимодействия
Этапы взаимодействия:
Инициализация сервера
Создание сокета
Привязка к адресу и порту
Перевод в режим прослушивания
Ожидание подключений
Подключение клиента
Создание сокета клиента
Установление соединения с сервером
Проверка успешности подключения
Обмен данными
Клиент отправляет запрос
Сервер обрабатывает запрос
Сервер отправляет ответ
Клиент получает ответ
Завершение сеанса
Закрытие соединения
Освобождение ресурсов
Средства языка для организации работы в сети
Программирование сетевых приложений
Состояния соединения:
CLOSED - соединение закрыто
LISTEN - сервер ожидает подключений
SYN_SENT - клиент отправил запрос на соединение
SYN_RECEIVED - сервер получил запрос
ESTABLISHED - соединение установлено
FIN_WAIT - инициация закрытия соединения
CLOSE_WAIT - ожидание закрытия
TIME_WAIT - ожидание перед полным закрытием
Средства языка для организации работы в сети
Программирование сетевых приложений
Преимущества клиент-серверной архитектуры
1. Централизованное управление данными
Все данные хранятся на сервере
Единая точка контроля и администрирования
Упрощенное резервное копирование и восстановление
Централизованная система безопасности
2. Масштабируемость
Возможность увеличения мощности сервера
Кластеризация и балансировка нагрузки
Разделение функций между несколькими серверами
Горизонтальное и вертикальное масштабирование
3. Безопасность
Контроль доступа на уровне сервера
Защита данных от несанкционированного доступа
Возможность шифрования канала связи
Аудит и логирование действий
4. Разделение ответственности
Четкое разделение функций между клиентом и сервером
Упрощение разработки и поддержки
Возможность независимого обновления компонентов
Специализация разработчиков
5. Эффективность использования ресурсов
Централизованные вычислительные мощности
Экономия ресурсов клиентских устройств
Оптимизация работы с данными
Кэширование и предобработка данных
Средства языка для организации работы в сети
Программирование сетевых приложений
Недостатки клиент-серверной архитектуры
1. Зависимость от сервера
Одиночная точка отказа
Необходимость высокой доступности сервера
Сложность обеспечения отказоустойчивости
2. Сложность администрирования
Требуются квалифицированные администраторы
Необходимость постоянного мониторинга
Сложность диагностики проблем
Средства языка для организации работы в сети
Программирование сетевых приложений
3. Пропускная способность сети
Ограничение скорости передачи данных
Зависимость от качества сетевого соединения
Возможные задержки при передаче данных
Средства языка для организации работы в сети
Программирование сетевых приложений
Паттерны проектирования для клиент-серверных приложений
1. Паттерн "Запрос-Ответ" (Request-Response)
Синхронное взаимодействие
Клиент ждет ответа перед продолжением работы
Примеры: HTTP, RPC
2. Паттерн "Односторонняя передача" (One-way)
Асинхронное взаимодействие
Клиент не ждет подтверждения
Примеры: UDP, сообщения очередей
3. Паттерн "Публикация-Подписка" (Publish-Subscribe)
Клиенты подписываются на события
Сервер рассылает уведомления подписчикам
Примеры: MQTT, WebSocket, системы очередей
4. Паттерн "Долгое опросное соединение" (Long Polling)
Клиент устанавливает длительное соединение
Сервер держит соединение открытым до появления данных
Используется для реализации push-уведомлений
Средства языка для организации работы в сети
Программирование сетевых приложений
Примеры клиент-серверных приложений
1. Веб-приложения
Браузер (клиент) ←→ Веб-сервер
Используют протокол HTTP/HTTPS
Запросы на получение веб-страниц и ресурсов
2. Электронная почта
Почтовый клиент ←→ Почтовый сервер
Протоколы: SMTP, POP3, IMAP
Отправка и получение сообщений
3. Файловые сервисы
FTP-клиент ←→ FTP-сервер
Загрузка и выгрузка файлов
Управление файловой системой на сервере
4. Системы обмена сообщениями
Мессенджер (клиент) ←→ Сервер обмена сообщениями
Передача текстовых и мультимедийных сообщений
Групповые чаты и конференции
Средства языка для организации работы в сети
Программирование сетевых приложений
Безопасность в клиент-серверных приложениях
1. Аутентификация
Проверка подлинности клиента
Методы: пароли, токены, сертификаты
Многофакторная аутентификация
2. Авторизация
Контроль доступа к ресурсам
Определение прав и привилегий
Ролевая модель доступа
3. Шифрование
Защита данных при передаче
Протоколы: SSL/TLS, SSH
Симметричное и асимметричное шифрование
4. Защита от атак
Защита от перехвата данных (sniffing)
Защита от подмены данных (spoofing)
Защита от отказа в обслуживании (DoS)
Проверка входных данных
Средства языка для организации работы в сети
Программирование сетевых приложений
Internet-адресация
Основы IP-адресации
IP-адресация - это система логических адресов, используемая для идентификации устройств в сети и обеспечения маршрутизации данных между ними. IP-адреса работают на сетевом уровне (3 уровень) модели OSI.
Принципы IP-адресации:
Каждое устройство в сети имеет уникальный IP-адрес
IP-адрес состоит из двух частей: сетевой и хостовой
Адреса используются для маршрутизации пакетов
Поддерживаются два основных стандарта: IPv4 и IPv6
Средства языка для организации работы в сети
Программирование сетевых приложений
IPv4 (Internet Protocol версия 4)
Структура IPv4-адреса
Размер : 32 бита (4 байта)
Формат записи : четыре десятичных числа, разделенные точками (например, 192.168.1.1)
Диапазон значений : от 0.0.0.0 до 255.255.255.255
Количество возможных адресов : 2³² = 4,294,967,296 адресов
Средства языка для организации работы в сети
Программирование сетевых приложений
Классовая адресация IPv4
Класс
Диапазон первого октета
Маска по умолчанию
Количество сетей
Количество хостов
A
1-126
255.0.0.0
126
16,777,214
B
128-191
255.255.0.0
16,384
65,534
C
192-223
255.255.255.0
2,097,152
254
D
224-239
-
Мультикаст
-
E
240-255
-
Экспериментальные
-
Средства языка для организации работы в сети
Программирование сетевых приложений
Специальные IPv4-адреса
Адрес/Диапазон
Назначение
0.0.0.0
Неопределенный адрес, адрес по умолчанию
127.0.0.0/8
Адреса обратной петли (loopback)
10.0.0.0/8
Частная сеть класса A
172.16.0.0/12
Частная сеть класса B
192.168.0.0/16
Частная сеть класса C
169.254.0.0/16
Автоматические частные IP-адреса (APIPA)
255.255.255.255
Широковещательный адрес
Средства языка для организации работы в сети
Программирование сетевых приложений
Подсети (Subnetting)
Маска подсети - это 32-битное число, которое определяет, какая часть IP-адреса относится к сети, а какая - к хосту.
Формулы подсетей:
Количество подсетей = 2ⁿ, где n - количество заимствованных битов
Количество хостов в подсети = 2ᵐ - 2, где m - количество битов хоста
CIDR-нотация (Classless Inter-Domain Routing):
Формат: IP-адрес/префикс (например, 192.168.1.0/24)
Префикс указывает количество битов сетевой части
Средства языка для организации работы в сети
Программирование сетевых приложений
Примеры CIDR:
/24 = 255.255.255.0 = 256 адресов (254 хоста)
/25 = 255.255.255.128 = 128 адресов (126 хостов)
/26 = 255.255.255.192 = 64 адреса (62 хоста)
/27 = 255.255.255.224 = 32 адреса (30 хостов)
Средства языка для организации работы в сети
Программирование сетевых приложений
IPv6 (Internet Protocol версия 6)
Необходимость IPv6
Исчерпание адресного пространства IPv4 - рост числа устройств в Интернете
Улучшенная маршрутизация - иерархическая структура адресов
Безопасность - встроенная поддержка IPsec
Автоконфигурация - упрощенное подключение устройств
Производительность - оптимизированная структура заголовков
Средства языка для организации работы в сети
Программирование сетевых приложений
Структура IPv6-адреса
Размер : 128 бит (16 байтов)
Формат записи : восемь групп по четыре шестнадцатеричных цифры, разделенных двоеточиями
Пример : 2001:0db8:85a3:0000:0000:8a2e:0370:7334
Сокращенная запись : 2001:db8:85a3::8a2e:370:7334
Количество возможных адресов : 2¹²⁸ ≈ 3.4 × 10³⁸ адресов
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы IPv6-адресов
Тип
Диапазон
Назначение
Unicast (одноадресный)
2000::/3
Обычные адреса узлов
Multicast (групповой)
FF00::/8
Групповые адреса
Anycast (любойадресный)
-
Адрес ближайшего узла
Link-local
FE80::/10
Локальная сеть
Site-local
FEC0::/10
Частная сеть (устарел)
Loopback
::1/128
Обратная петля
Unspecified
::/128
Неопределенный адрес
Средства языка для организации работы в сети
Программирование сетевых приложений
Форматы IPv6-адресов
Глобальный unicast-адрес:
| 48 бит (глобальный префикс) | 16 бит (подсеть) | 64 бита (интерфейс) |
Link-local адрес:
FE80:: + 54 нулевых бита + 64-битный идентификатор интерфейса
IPv4-совместимый адрес:
::ffff:192.168.1.1 (последние 32 бита - IPv4-адрес)
Средства языка для организации работы в сети
Программирование сетевых приложений
Порты (Ports)
Основы портов
Порт - это 16-битное число, используемое для идентификации процессов или служб в пределах одного IP-адреса.
Диапазон портов : 0-65535 (2¹⁶ возможных портов)
Размер : 16 бит
Формат : TCP/UDP порт
Назначение : мультиплексирование соединений
Средства языка для организации работы в сети
Программирование сетевых приложений
Классификация портов
Диапазон
Категория
Назначение
Примеры
0-1023
Зарезервированные (Well-known)
Системные службы
HTTP (80), FTP (21), SSH (22)
1024-49151
Зарегистрированные (Registered)
Прикладные службы
MySQL (3306), PostgreSQL (5432)
49152-65535
Динамические (Dynamic/Private)
Временные соединения
Клиентские порты
Средства языка для организации работы в сети
Программирование сетевых приложений
Назначение портов
Идентификация служб - каждая служба имеет стандартный порт
Мультиплексирование - несколько соединений на одном IP-адресе
Безопасность - контроль доступа к службам
Маршрутизация - направление трафика к нужному процессу
Средства языка для организации работы в сети
Программирование сетевых приложений
DNS (Domain Name System)
Назначение DNS
DNS - это распределенная система доменных имен, которая преобразует удобочитаемые доменные имена (например, www.example.com) в IP-адреса (например, 93.184.216.34).
Средства языка для организации работы в сети
Программирование сетевых приложений
Иерархия DNS
Корневые серверы (.)
↓
Серверы верхнего уровня (.com, .org, .ru и т.д.)
↓
Серверы второго уровня (example.com)
↓
Локальные DNS-серверы
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы DNS-записей
Тип записи
Назначение
Пример
A
IPv4-адрес
example.com → 93.184.216.34
AAAA
IPv6-адрес
example.com → 2001:db8::1
CNAME
Псевдоним (alias)
www.example.com → example.com
MX
Почтовый сервер
mail.example.com
NS
DNS-сервер
ns1.example.com
PTR
Обратная запись
34.216.184.93.in-addr.arpa → example.com
TXT
Текстовая информация
SPF, DKIM записи
SRV
Сервис
_sip._tcp.example.com
Средства языка для организации работы в сети
Программирование сетевых приложений
Процесс разрешения DNS
Локальный кэш - проверка локального кэша браузера и ОС
Локальный DNS-сервер - запрос к настроенному DNS-серверу
Рекурсивный запрос - локальный сервер делает запросы от имени клиента
Корневые серверы - получение информации о серверах верхнего уровня
Серверы верхнего уровня - получение информации об авторитетных серверах
Авторитетные серверы - получение конечного IP-адреса
Средства языка для организации работы в сети
Программирование сетевых приложений
Кэширование DNS
Время жизни записи (TTL) - определяет, как долго запись хранится в кэше
Иерархическое кэширование - кэш на разных уровнях (браузер, ОС, локальный DNS)
Обновление кэша - периодическое обновление записей по истечении TTL
Средства языка для организации работы в сети
Программирование сетевых приложений
Маршрутизация (Routing)
Основы маршрутизации
Маршрутизация - это процесс определения оптимального пути для передачи пакетов от источника к назначению.
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы маршрутизации
Статическая маршрутизация
Маршруты задаются вручную администратором
Не требует дополнительных ресурсов
Подходит для простых сетей
Не адаптируется к изменениям в сети
Динамическая маршрутизация
Маршруты определяются автоматически
Используются протоколы маршрутизации
Адаптируется к изменениям в сети
Требует дополнительных ресурсов
Средства языка для организации работы в сети
Программирование сетевых приложений
Протоколы маршрутизации
Протокол
Тип
Метрика
Область применения
RIP
Distance Vector
Количество хопов
Малые сети
OSPF
Link State
Стоимость связи
Средние и большие сети
BGP
Path Vector
Политика, AS-путь
Интернет
EIGRP
Hybrid
Составная метрика
Сети Cisco
Средства языка для организации работы в сети
Программирование сетевых приложений
Таблица маршрутизации
Содержит информацию о:
Сети назначения
Маске подсети
Шлюзе (Gateway)
Интерфейсе
Метрике маршрута
Приоритете маршрута
Средства языка для организации работы в сети
Программирование сетевых приложений
NAT (Network Address Translation)
Назначение NAT
NAT - это технология преобразования IP-адресов, позволяющая нескольким устройствам в частной сети использовать один публичный IP-адрес для доступа в Интернет.
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы NAT
Статический NAT (One-to-One)
Один частный IP-адрес → один публичный IP-адрес
Используется для серверов, требующих постоянного адреса
Динамический NAT (Many-to-Many)
Пул частных IP-адресов → пул публичных IP-адресов
Адреса назначаются по мере необходимости
PAT (Port Address Translation) / NAT Overload
Множество частных IP-адресов → один публичный IP-адрес
Используются порты для различения соединений
Наиболее распространенный тип NAT
Средства языка для организации работы в сети
Программирование сетевых приложений
Преимущества NAT:
Экономия публичных IP-адресов
Безопасность - скрытие внутренней структуры сети
Гибкость - возможность изменения внутренней адресации
Совместимость - работа с различными протоколами
Недостатки NAT:
Сложность для некоторых протоколов (FTP, VoIP)
Проблемы с безопасностью при неправильной настройке
Ограничения для пиринговых приложений
Дополнительная задержка при обработке пакетов
Средства языка для организации работы в сети
Программирование сетевых приложений
Обзор сокетов
Что такое сокет?
Сокет (socket) - это абстрактный механизм межпроцессного взаимодействия, представляющий собой конечную точку сетевого соединения. Сокет является основой всех сетевых коммуникаций в современных операционных системах.
Средства языка для организации работы в сети
Программирование сетевых приложений
Основные характеристики сокетов:
Точка взаимодействия между процессами (как локальными, так и удаленными)
Комбинация IP-адреса и порта (например, 192.168.1.100:8080)
Предоставляет интерфейс для сетевого взаимодействия через системные вызовы
Поддерживает как однонаправленную, так и двунаправленную передачу данных
Средства языка для организации работы в сети
Программирование сетевых приложений
Архитектура сокетов:
Приложение → Сокет API → Транспортный уровень (TCP/UDP) → Сетевой уровень (IP) → Канальный уровень
История и стандарты
Первоначально разработаны в BSD Unix (1983 год)
Стандартизированы в POSIX.1-2001
Реализованы во всех современных ОС (Windows, Linux, macOS)
Являются универсальным интерфейсом для сетевого программирования
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы сокетов по семейству адресов
1. AF_INET (IPv4)
Используются для сетевого взаимодействия через протокол IPv4
Адрес: 32-битный IP-адрес + 16-битный порт
Наиболее распространенный тип
2. AF_INET6 (IPv6)
Поддерживают протокол IPv6
Адрес: 128-битный IP-адрес + 16-битный порт
Обеспечивают больший адресный простор
3. AF_UNIX (AF_LOCAL)
Используются для локального межпроцессного взаимодействия
Не требуют сетевого стека
Обеспечивают высокую производительность
Средства языка для организации работы в сети
Программирование сетевых приложений
Типы сокетов по типу взаимодействия
1. SOCK_STREAM (потоковые сокеты)
Протокол : TCP (Transmission Control Protocol)
Характеристики :
Надежная доставка данных
Упорядоченная передача (без потерь и дублирования)
Установление соединения (трехэтапное рукопожатие)
Двунаправленный поток данных
Применение : HTTP, FTP, SMTP, SSH и другие протоколы, требующие надежности
Средства языка для организации работы в сети
Программирование сетевых приложений
2. SOCK_DGRAM (дейтаграммные сокеты)
Протокол : UDP (User Datagram Protocol)
Характеристики :
Без установления соединения
Не гарантирует доставку
Не гарантирует порядок доставки
Минимальные накладные расходы
Применение : DNS, DHCP, VoIP, онлайн-игры, потоковое видео
Средства языка для организации работы в сети
Программирование сетевых приложений
3. SOCK_RAW (сырые сокеты)
Прямой доступ к сетевому уровню
Возможность формировать собственные заголовки протоколов
Требуют привилегированного доступа (root/administrator)
Используются для создания сетевых утилит (ping, traceroute)
Средства языка для организации работы в сети
Программирование сетевых приложений
Жизненный цикл сокета
1. Создание сокета
int socket_fd = socket (AF_INET, SOCK_STREAM, 0 );
2. Привязка к адресу (для сервера)
bind (socket_fd, (struct sockaddr*)&address, sizeof (address));
Средства языка для организации работы в сети
Программирование сетевых приложений
3. Установление соединения
Клиент : connect()
Сервер : listen() → accept()
4. Обмен данными
send() / recv() для TCP
sendto() / recvfrom() для UDP
Средства языка для организации работы в сети
Программирование сетевых приложений
5. Закрытие соединения
close (socket_fd);
closesocket (socket_fd);
Средства языка для организации работы в сети
Программирование сетевых приложений
Системные вызовы для работы с сокетами
Основные функции:
socket() - создание сокета
bind() - привязка к локальному адресу
listen() - перевод в режим прослушивания
accept() - принятие входящего соединения
connect() - установление соединения
send()/recv() - передача данных (TCP)
sendto()/recvfrom() - передача данных (UDP)
close() - закрытие сокета
Средства языка для организации работы в сети
Программирование сетевых приложений
Дополнительные функции:
select() - мультиплексирование ввода/вывода
setsockopt() - установка параметров сокета
getsockopt() - получение параметров сокета
getsockname() - получение локального адреса
getpeername() - получение удаленного адреса
Средства языка для организации работы в сети
Программирование сетевых приложений
Параметры сокетов (Socket Options)
Важные опции:
SO_REUSEADDR - повторное использование локального адреса
SO_KEEPALIVE - поддержание соединения активным
SO_RCVBUF/SO_SNDBUF - размер буферов приема/передачи
TCP_NODELAY - отключение алгоритма Нейгла
SO_LINGER - управление закрытием соединения
Средства языка для организации работы в сети
Программирование сетевых приложений
Блокирующие и неблокирующие режимы
Блокирующий режим (по умолчанию):
Операции ввода/вывода блокируют выполнение программы
Простота программирования
Неэффективность при работе с несколькими соединениями
Неблокирующий режим:
Операции возвращаются немедленно
Требует использования механизмов опроса (select, poll, epoll)
Эффективен для высоконагруженных приложений
Средства языка для организации работы в сети
Программирование сетевых приложений
Преимущества использования сокетов
Универсальность - стандартный интерфейс для всех платформ
Гибкость - поддержка различных протоколов и типов соединений
Контроль - полный контроль над процессом передачи данных
Производительность - прямой доступ к транспортному уровню
Совместимость - работа между различными операционными системами
Средства языка для организации работы в сети
Программирование сетевых приложений
Недостатки и ограничения
Сложность - необходимость ручного управления многими аспектами
Безопасность - отсутствие встроенных механизмов шифрования
Переносимость - различия в реализации между платформами
Отладка - сложность диагностики сетевых проблем
Средства языка для организации работы в сети
Программирование сетевых приложений
Теория сетевых протоколов
TCP (Transmission Control Protocol)
Основные характеристики TCP:
Надежная доставка - гарантирует доставку всех данных
Упорядоченная передача - данные приходят в правильном порядке
Контроль потока - предотвращает перегрузку получателя
Контроль перегрузки - адаптируется к состоянию сети
Двунаправленный поток данных - полный дуплекс
Средства языка для организации работы в сети
Программирование сетевых приложений
Структура TCP-сегмента:
[Заголовок TCP | Данные]
Порты источника и назначения (16 бит каждый)
Номер последовательности (32 бита)
Номер подтверждения (32 бита)
Флаги управления (SYN, ACK, FIN, RST, PSH, URG)
Размер окна (16 бит) - контроль потока
Контрольная сумма (16 бит)
Средства языка для организации работы в сети
Программирование сетевых приложений
Процесс установления TCP-соединения (трехэтапное рукопожатие):
SYN : клиент отправляет запрос на соединение
SYN-ACK : сервер подтверждает получение и отправляет свой запрос
ACK : клиент подтверждает получение
Клиент Сервер
| |
|-------- SYN --------> |
| |
|<----- SYN-ACK ------- |
| |
|-------- ACK --------> |
| |
Средства языка для организации работы в сети
Программирование сетевых приложений
Процесс завершения TCP-соединения (четырехэтапное завершение):
FIN : инициатор отправляет запрос на завершение
ACK : получатель подтверждает получение
FIN : получатель отправляет запрос на завершение
ACK : инициатор подтверждает получение
Алгоритмы и механизмы TCP:
Алгоритм Нейгла - объединение маленьких пакетов
Алгоритм медленного старта - постепенное увеличение скорости передачи
Алгоритм устранения перегрузки - реакция на потери пакетов
Таймеры повторной передачи - контроль времени ожидания подтверждений
Средства языка для организации работы в сети
Программирование сетевых приложений
UDP (User Datagram Protocol)
Основные характеристики UDP:
Без установления соединения - данные отправляются немедленно
Ненадежная доставка - нет гарантии доставки
Без упорядочивания - пакеты могут прийти в неправильном порядке
Минимальные накладные расходы - всего 8 байт заголовка
Границы сообщений сохраняются - датаграммы не разбиваются
Средства языка для организации работы в сети
Программирование сетевых приложений
Структура UDP-датаграммы:
[Заголовок UDP (8 байт) | Данные]
Порт источника (16 бит)
Порт назначения (16 бит)
Длина датаграммы (16 бит)
Контрольная сумма (16 бит, опционально)
Преимущества UDP:
Низкая задержка - отсутствие установления соединения
Высокая скорость - минимальная обработка
Возможность широковещательной передачи (broadcast)
Гибкость - приложение само контролирует надежность
Средства языка для организации работы в сети
Программирование сетевых приложений
Приложения, использующие UDP:
DNS (порт 53) - система доменных имен
DHCP (порты 67/68) - динамическая конфигурация хостов
VoIP - голосовая связь по IP
Видеостриминг - онлайн-трансляции
Онлайн-игры - передача игровых данных
SNMP - сетевое управление
Средства языка для организации работы в сети
Программирование сетевых приложений
Сравнение TCP и UDP
Характеристика
TCP
UDP
Надежность
Гарантированная
Не гарантирована
Упорядочивание
Сохраняется порядок
Порядок не гарантирован
Соединение
Устанавливается
Не устанавливается
Скорость
Медленнее
Быстрее
Размер заголовка
20+ байт
8 байт
Потоковая передача
Поддерживается
Только сообщения
Контроль перегрузки
Есть
Нет
Широковещательность
Нет
Да
Средства языка для организации работы в сети
Программирование сетевых приложений
Сетевые классы Qt
Основные классы для работы с сетью
QTcpSocket - TCP-клиент
QTcpServer - TCP-сервер
QUdpSocket - UDP-сокет
QHostAddress - IP-адрес
QNetworkAccessManager - HTTP-клиент
QNetworkRequest - HTTP-запрос
QNetworkReply - HTTP-ответ
Средства языка для организации работы в сети
Программирование сетевых приложений
TCP-клиент на Qt
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
class TcpClient : public QObject {
Q_OBJECT
private :
QTcpSocket* socket;
public :
TcpClient (QObject* parent = nullptr ) : QObject (parent) {
socket = new QTcpSocket (this );
connect (socket, &QTcpSocket::connected, this , &TcpClient::onConnected);
connect (socket, &QTcpSocket::readyRead, this , &TcpClient::onReadyRead);
connect (socket, &QTcpSocket::disconnected, this , &TcpClient::onDisconnected);
socket->connectToHost (QHostAddress ("127.0.0.1" ), 8080 );
}
private slots:
void onConnected () {
qDebug () << "Подключено к серверу" ;
socket->write ("Hello, Server!" );
}
void onReadyRead () {
QByteArray data = socket->readAll ();
qDebug () << "Получено:" << data;
}
void onDisconnected () {
qDebug () << "Отключено от сервера" ;
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
TCP-сервер на Qt
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
class TcpServer : public QObject {
Q_OBJECT
private :
QTcpServer* server;
QList<QTcpSocket*> clients;
public :
TcpServer (QObject* parent = nullptr ) : QObject (parent) {
server = new QTcpServer (this );
connect (server, &QTcpServer::newConnection,
this , &TcpServer::onNewConnection);
if (server->listen (QHostAddress::Any, 8080 )) {
qDebug () << "Сервер запущен на порту 8080" ;
} else {
qDebug () << "Ошибка запуска сервера:" << server->errorString ();
}
}
private slots:
void onNewConnection () {
QTcpSocket* clientSocket = server->nextPendingConnection ();
clients.append (clientSocket);
connect (clientSocket, &QTcpSocket::readyRead,
this , &TcpServer::onReadyRead);
connect (clientSocket, &QTcpSocket::disconnected,
this , &TcpServer::onDisconnected);
qDebug () << "Новый клиент подключен:"
<< clientSocket->peerAddress ().toString ();
}
void onReadyRead () {
QTcpSocket* client = qobject_cast <QTcpSocket*>(sender ());
QByteArray data = client->readAll ();
qDebug () << "Получено от клиента:" << data;
for (QTcpSocket* c : clients) {
c->write ("Сообщение получено: " + data);
}
}
void onDisconnected () {
QTcpSocket* client = qobject_cast <QTcpSocket*>(sender ());
clients.removeAll (client);
client->deleteLater ();
qDebug () << "Клиент отключен" ;
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
UDP/Дейтаграммы на Qt
#include <QUdpSocket>
#include <QHostAddress>
#include <QDebug>
class UdpServer : public QObject {
Q_OBJECT
private :
QUdpSocket* udpSocket;
public :
UdpServer (QObject* parent = nullptr ) : QObject (parent) {
udpSocket = new QUdpSocket (this );
if (udpSocket->bind (QHostAddress::Any, 1234 )) {
qDebug () << "UDP сервер запущен на порту 1234" ;
connect (udpSocket, &QUdpSocket::readyRead,
this , &UdpServer::onReadyRead);
}
}
private slots:
void onReadyRead () {
while (udpSocket->hasPendingDatagrams ()) {
QByteArray datagram;
datagram.resize (udpSocket->pendingDatagramSize ());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram (datagram.data (), datagram.size (),
&sender, &senderPort);
qDebug () << "Получено от" << sender.toString ()
<< ":" << senderPort << "-" << datagram;
udpSocket->writeDatagram ("Ответ получен" , sender, senderPort);
}
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
UDP-клиент на Qt
#include <QUdpSocket>
#include <QHostAddress>
#include <QDebug>
class UdpClient : public QObject {
Q_OBJECT
private :
QUdpSocket* udpSocket;
public :
UdpClient (QObject* parent = nullptr ) : QObject (parent) {
udpSocket = new QUdpSocket (this );
connect (udpSocket, &QUdpSocket::readyRead,
this , &UdpClient::onReadyRead);
sendMessage ("Hello UDP Server!" );
}
void sendMessage (const QString& message) {
QByteArray datagram = message.toUtf8 ();
QHostAddress serverAddress ("127.0.0.1" ) ;
quint16 serverPort = 1234 ;
udpSocket->writeDatagram (datagram, serverAddress, serverPort);
qDebug () << "Отправлено:" << message;
}
private slots:
void onReadyRead () {
while (udpSocket->hasPendingDatagrams ()) {
QByteArray datagram;
datagram.resize (udpSocket->pendingDatagramSize ());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram (datagram.data (), datagram.size (),
&sender, &senderPort);
qDebug () << "Получено от" << sender.toString ()
<< ":" << senderPort << "-" << datagram;
}
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
HTTP-клиент на Qt
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDebug>
class HttpClient : public QObject {
Q_OBJECT
private :
QNetworkAccessManager* manager;
public :
HttpClient (QObject* parent = nullptr ) : QObject (parent) {
manager = new QNetworkAccessManager (this );
connect (manager, &QNetworkAccessManager::finished,
this , &HttpClient::onRequestFinished);
getRequest ("https://api.github.com/users/octocat" );
postRequest ("https://httpbin.org/post" , "{\"key\":\"value\"}" );
}
void getRequest (const QString& url) {
QNetworkRequest request (QUrl(url)) ;
request.setHeader (QNetworkRequest::ContentTypeHeader, "application/json" );
manager->get (request);
}
void postRequest (const QString& url, const QByteArray& data) {
QNetworkRequest request (QUrl(url)) ;
request.setHeader (QNetworkRequest::ContentTypeHeader, "application/json" );
manager->post (request, data);
}
private slots:
void onRequestFinished (QNetworkReply* reply) {
if (reply->error () == QNetworkReply::NoError) {
QByteArray response = reply->readAll ();
qDebug () << "Ответ:" << response;
} else {
qDebug () << "Ошибка:" << reply->errorString ();
}
reply->deleteLater ();
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Proxy-сервер на Qt
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
class ProxyServer : public QObject {
Q_OBJECT
private :
QTcpServer* server;
QString targetHost;
quint16 targetPort;
public :
ProxyServer (const QString& targetHost, quint16 targetPort,
QObject* parent = nullptr ) : QObject (parent) {
this ->targetHost = targetHost;
this ->targetPort = targetPort;
server = new QTcpServer (this );
connect (server, &QTcpServer::newConnection,
this , &ProxyServer::onNewConnection);
if (server->listen (QHostAddress::Any, 8888 )) {
qDebug () << "Прокси-сервер запущен на порту 8888" ;
}
}
private slots:
void onNewConnection () {
QTcpSocket* clientSocket = server->nextPendingConnection ();
QTcpSocket* targetSocket = new QTcpSocket (this );
targetSocket->connectToHost (targetHost, targetPort);
connect (clientSocket, &QTcpSocket::readyRead, [=]() {
if (targetSocket->state () == QAbstractSocket::ConnectedState) {
targetSocket->write (clientSocket->readAll ());
}
});
connect (targetSocket, &QTcpSocket::readyRead, [=]() {
clientSocket->write (targetSocket->readAll ());
});
connect (clientSocket, &QTcpSocket::disconnected, [=]() {
targetSocket->disconnectFromHost ();
clientSocket->deleteLater ();
targetSocket->deleteLater ();
});
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Работа с URL в Qt
#include <QUrl>
#include <QUrlQuery>
#include <QDebug>
class UrlExample {
public :
static void demonstrateUrlParsing () {
QUrl url ("https://api.example.com:8080/users?name=John&age=25#section" ) ;
qDebug () << "Схема:" << url.scheme ();
qDebug () << "Хост:" << url.host ();
qDebug () << "Порт:" << url.port ();
qDebug () << "Путь:" << url.path ();
qDebug () << "Запрос:" << url.query ();
qDebug () << "Фрагмент:" << url.fragment ();
QUrlQuery query (url) ;
qDebug () << "Параметры:" ;
for (auto it = query.queryItems ().begin ();
it != query.queryItems ().end (); ++it) {
qDebug () << " " << it->first << "=" << it->second;
}
QUrl newUrl ("https://example.com/search" ) ;
QUrlQuery newQuery;
newQuery.addQueryItem ("q" , "Qt network" );
newQuery.addQueryItem ("page" , "1" );
newUrl.setQuery (newQuery);
qDebug () << "Сформированный URL:" << newUrl.toString ();
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Зарезервированные сокеты (Well-Known Ports)
IANA (Internet Assigned Numbers Authority) выделяет три диапазона портов:
Диапазон
Назначение
Примеры
0-1023 (Well-Known)
Зарезервированы для системных служб
20/21 (FTP), 22 (SSH), 80 (HTTP), 443 (HTTPS)
1024-49151 (Registered)
Зарегистрированные для приложений
3306 (MySQL), 5432 (PostgreSQL), 6379 (Redis)
49152-65535 (Dynamic)
Динамические/частные порты
Временные порты для клиентских соединений
Правила использования портов
Порты 0-1023 требуют прав администратора (root/Administrator) для привязки (bind)
Для пользовательских серверов используйте порты из диапазона 1024-49151
Порт 0 — означает автоматический выбор свободного порта ОС
/etc/services (Linux) — реестр зарезервированных служб
Наиболее часто используемые порты в сетевом программировании
Порт
Протокол
Описание
80
HTTP
Веб-серверы (без шифрования)
443
HTTPS
Веб-серверы (SSL/TLS)
22
SSH
Безопасное удалённое управление
21
FTP
Передача файлов
3306
MySQL
База данных MySQL
5432
PostgreSQL
База данных PostgreSQL
6379
Redis
In-memory хранилище
8080
HTTP (alt)
Альтернативный HTTP-порт (часто используется для тестов)
Средства языка для организации работы в сети
Программирование сетевых приложений
Обработка ошибок в сетевых приложениях
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QDebug>
class NetworkErrorHandler : public QObject {
Q_OBJECT
public :
static QString getErrorDescription (QAbstractSocket::SocketError error) {
switch (error) {
case QAbstractSocket::ConnectionRefusedError:
return "Соединение отклонено" ;
case QAbstractSocket::RemoteHostClosedError:
return "Удаленный хост закрыл соединение" ;
case QAbstractSocket::HostNotFoundError:
return "Хост не найден" ;
case QAbstractSocket::SocketAccessError:
return "Нет доступа к сокету" ;
case QAbstractSocket::SocketResourceError:
return "Не хватает системных ресурсов" ;
case QAbstractSocket::SocketTimeoutError:
return "Таймаут соединения" ;
case QAbstractSocket::DatagramTooLargeError:
return "Датаграмма слишком велика" ;
case QAbstractSocket::NetworkError:
return "Ошибка сети" ;
case QAbstractSocket::AddressInUseError:
return "Адрес уже используется" ;
default :
return "Неизвестная ошибка" ;
}
}
static void handleNetworkError (QAbstractSocket* socket) {
connect (socket, QOverload<QAbstractSocket::SocketError>::of (&QAbstractSocket::error),
[=](QAbstractSocket::SocketError socketError) {
qDebug () << "Ошибка сети:" << getErrorDescription (socketError);
qDebug () << "Детали:" << socket->errorString ();
});
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Асинхронная работа с сетью
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QTimer>
class AsyncNetworkExample {
public :
static QByteArray syncRequest (const QString& url) {
QNetworkAccessManager manager;
QNetworkRequest request (QUrl(url)) ;
QNetworkReply* reply = manager.get (request);
QEventLoop loop;
QObject::connect (reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
QTimer::singleShot (5000 , &loop, &QEventLoop::quit);
loop.exec ();
if (reply->error () == QNetworkReply::NoError) {
return reply->readAll ();
} else {
return QByteArray ();
}
}
static void asyncRequest (const QString& url) {
QNetworkAccessManager* manager = new QNetworkAccessManager ();
QNetworkRequest request (QUrl(url)) ;
QNetworkReply* reply = manager->get (request);
QObject::connect (reply, &QNetworkReply::finished, [=]() {
if (reply->error () == QNetworkReply::NoError) {
qDebug () << "Ответ получен:" << reply->readAll ();
} else {
qDebug () << "Ошибка:" << reply->errorString ();
}
reply->deleteLater ();
manager->deleteLater ();
});
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Безопасность в сетевых приложениях
#include <QSslSocket>
#include <QSslCertificate>
#include <QSslKey>
class SecureNetworkExample {
public :
static void createSecureConnection () {
QSslSocket* socket = new QSslSocket ();
connect (socket, &QSslSocket::encrypted, []() {
qDebug () << "Соединение зашифровано" ;
});
connect (socket, &QSslSocket::sslErrors, [](const QList<QSslError>& errors) {
for (const QSslError& error : errors) {
qDebug () << "SSL ошибка:" << error.errorString ();
}
});
socket->connectToHostEncrypted ("api.github.com" , 443 );
connect (socket, &QSslSocket::peerVerifyError, [](const QSslError& error) {
qDebug () << "Ошибка проверки сертификата:" << error.errorString ();
});
socket->setPeerVerifyMode (QSslSocket::VerifyPeer);
}
static void loadCertificates () {
QSslSocket* socket = new QSslSocket ();
QList<QSslCertificate> certificates = QSslCertificate::fromPath ("client.crt" );
if (!certificates.isEmpty ()) {
socket->setLocalCertificate (certificates.first ());
}
QFile keyFile ("client.key" ) ;
if (keyFile.open (QIODevice::ReadOnly)) {
QSslKey privateKey (keyFile.readAll(), QSsl::Rsa) ;
socket->setPrivateKey (privateKey);
}
}
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Производительность и оптимизация
Советы по оптимизации сетевых приложений
Используйте буферы нужного размера
socket->setReadBufferSize (64 * 1024 );
Объединяйте маленькие сообщения
socket->write (message1);
socket->write (message2);
socket->flush ();
Средства языка для организации работы в сети
Программирование сетевых приложений
Используйте сжатие данных
QByteArray compressed = qCompress (data, 9 );
Реализуйте пул соединений
class ConnectionPool {
QList<QTcpSocket*> availableSockets;
};
Средства языка для организации работы в сети
Программирование сетевых приложений
Лучшие практики
1. Обработка ошибок
Всегда проверяйте возвращаемые значения
Используйте сигналы об ошибках
Логируйте важные события
2. Безопасность
Используйте шифрование (SSL/TLS)
Проверяйте входные данные
Реализуйте аутентификацию
Средства языка для организации работы в сети
Программирование сетевых приложений
3. Производительность
Используйте асинхронные операции
Реализуйте кэширование
Оптимизируйте размер пакетов
4. Масштабируемость
Используйте многопоточность
Реализуйте балансировку нагрузки
Применяйте паттерны проектирования
Средства языка для организации работы в сети
Программирование сетевых приложений
Резюме
Ключевые концепции
Сокеты - основа сетевого взаимодействия
Qt Network - мощный инструментарий для сетевого программирования
TCP vs UDP - выбор протокола в зависимости от задачи
Безопасность - важный аспект сетевых приложений
Асинхронность - ключ к отзывчивым приложениям
Дальнейшее изучение
Многопоточные сетевые приложения
Веб-сокеты (WebSockets)
Пиринговые сети (P2P)
Облачные технологии
Микросервисная архитектура
Средства языка для организации работы в сети
Программирование сетевых приложений
Вопросы для самопроверки
В чем различие между TCP и UDP?
Какие классы Qt используются для HTTP-запросов?
Как обрабатывать сетевые ошибки?
Что такое прокси-сервер и как его реализовать?
Как обеспечить безопасность сетевого соединения?
Средства языка для организации работы в сети
Заметки докладчика:
- Это КЛЮЧЕВАЯ лекция курса — 6 академических часов.
- Лекция очень объёмная (1758 строк), рекомендуется разбить на два занятия:
- Занятие 1: теория — OSI, IP-адресация, DNS, TCP/UDP, клиент-серверная архитектура.
- Занятие 2: практика — Qt TCP-сервер/клиент, UDP, HTTP, proxy-сервер.
- При ограниченном времени фокусируйтесь на уровнях 4 (Транспортный) и 7 (Прикладной) — именно с ними работают программисты.
Заметки докладчика:
- Содержание OSI пересекается с лекцией 02. Если студенты уже изучали — быстрый обзор и переход далее.
- Программистам важны в первую очередь уровни 4 (Транспортный — TCP/UDP) и 7 (Прикладной — HTTP, DNS).
- Остальные уровни — для понимания контекста, но не для повседневной работы.
- QoS и устройства по уровням — можно сократить при нехватке времени.
Заметки докладчика:
- Студенты обязаны знать: приватные диапазоны (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback (127.0.0.1), localhost.
- IPv6 всё важнее — покажите реальные IPv6-адреса (ifconfig / ip addr на машине).
- В Qt: QHostAddress обрабатывает оба формата автоматически.
- Частый вопрос на экзамене: «какой адрес у localhost?» — 127.0.0.1 (IPv4), ::1 (IPv6).
Заметки докладчика:
- DNS-разрешение — первый шаг любого сетевого соединения. Без DNS клиент не знает, куда подключаться.
- В Qt: QHostInfo::lookupHost() — асинхронное DNS-разрешение через сигналы/слоты.
- Кэширование DNS снижает задержку: браузер → ОС → локальный DNS-сервер → рекурсивный запрос.
- DNS — иерархическая распределённая база данных, не централизованный сервер.
- Продемонстрируйте: nslookup, dig, или QHostInfo::fromName() в Qt.
Заметки докладчика:
- Трёхэтапное рукопожатие SYN → SYN-ACK → ACK нужно ЗНАТЬ НАИЗУСТЬ — частый вопрос на экзамене.
- Покажите захват в Wireshark — студенты должны увидеть эти пакеты своими глазами.
- В Qt: QTcpSocket::connectToHost() инкапсулирует всё рукопожатие — программисту не нужно управлять им вручную.
- Завершение: 4-этапное (FIN→ACK→FIN→ACK) — тоже стоит упомянуть.
Заметки докладчика:
- Это основа для лабораторной работы (Echo-сервер). Убедитесь, что студенты разобрались.
- Ключевой паттерн: сервер слушает → принимает → создаёт обработчик на клиента → сигналы/слоты для асинхронного I/O.
- deleteLater() — критически важно для предотвращения утечек памяти. Объясните, почему нельзя вызвать delete напрямую (событийный цикл может обращаться к объекту после удаления).
- Для усложнения: добавьте хранение списка клиентов, рассылку сообщений (чат).
Заметки докладчика:
- Proxy-сервер — хороший пример двунаправленной пересылки данных.
- Читаем от клиента → пишем на сервер, читаем с сервера → пишем клиенту.
- Оба направления должны обрабатываться асинхронно (сигналы/слоты).
- Обратите внимание на deleteLater() для обоих сокетов при отключении клиента.
- Упражнение для студентов: добавить логирование пересылаемых данных, подсчёт байт.
Заметки докладчика:
- Зарезервированные сокеты (well-known ports) — обязательный пункт учебной программы.
- Студенты часто путают: bind() к порту <1024 на Linux требует sudo. В курсовых проектах использовать порты > 1024.
- Порт 8080 — де-факто стандарт для тестовых серверов в учебных заведениях.
- QTcpServer::listen(QHostAddress::Any, 0) — передаём 0, ОС выберет свободный порт, можно узнать через serverPort().
Заметки докладчика:
Ожидаемые ответы на вопросы самопроверки:
1. TCP — надёжный, с установлением соединения, упорядоченная доставка. UDP — ненадёжный, без соединения, быстрый, сохраняет границы сообщений.
2. QNetworkAccessManager — основной класс. QNetworkRequest для формирования запроса, QNetworkReply для получения ответа.
3. Обработка сигнала errorOccurred (или QOverload<QAbstractSocket::SocketError>), проверка QNetworkReply::NetworkError, информативные сообщения для пользователя.
4. Прокси-сервер — промежуточный узел между клиентом и целевым сервером. Реализация: QTcpServer принимает подключения, создаёт QTcpSocket к целевому серверу, пересылает данные в обоих направлениях через сигналы/слоты.
5. Использование HTTPS (QSslSocket), валидация SSL-сертификатов, аутентификация, не хранить пароли в открытом виде, проверка входных данных.